////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2001.
// -------------------------------------------------------------------------
//  File name:   CloudObject.cpp
//  Version:     v1.00
//  Created:     05/02/2005 by Sergiy Shaykin.
//  Compilers:   Visual C++ 6.0
//  Description: CCloudObject implementation.
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "CloudObject.h"
#include "Viewport.h"

#include "SegmentedWorld/SegmentedWorldManager.h"

//////////////////////////////////////////////////////////////////////////
// CBase implementation.
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CCloudObject,CBaseObject)


//////////////////////////////////////////////////////////////////////////
CCloudObject::CCloudObject()
{
	m_bNotSharedGeom = false;
	m_bIgnoreNodeUpdate = false;

	m_width = 1;
	m_height = 1;
	m_length = 1;
	mv_spriteRow = -1;
	m_angleVariations = 0.0f;

	mv_sizeSprites = 0;
	mv_randomSizeValue = 0;

	AddVariable( mv_spriteRow,"SpritesRow","Sprites Row");
	mv_spriteRow.SetLimits(-1, 64);
	AddVariable( m_width,"Width",functor(*this,&CCloudObject::OnSizeChange) );
	m_width.SetLimits(0, 99999);
	AddVariable( m_height,"Height",functor(*this,&CCloudObject::OnSizeChange) );
	m_height.SetLimits(0, 99999);
	AddVariable( m_length,"Length",functor(*this,&CCloudObject::OnSizeChange) );
	m_length.SetLimits(0, 99999);
	AddVariable( m_angleVariations,"AngleVariations","Angle Variations",functor(*this,&CCloudObject::OnSizeChange), IVariable::DT_ANGLE );
	m_angleVariations.SetLimits(0, 99999);

	AddVariable( mv_sizeSprites,"SizeofSprites", "Size of Sprites",functor(*this,&CCloudObject::OnSizeChange));
	mv_sizeSprites.SetLimits(0, 99999);
	AddVariable( mv_randomSizeValue,"SizeVariation","Size Variation",functor(*this,&CCloudObject::OnSizeChange) );
	mv_randomSizeValue.SetLimits(0, 99999);

	SetColor( RGB(127,127,255) );
}

//////////////////////////////////////////////////////////////////////////
void CCloudObject::OnSizeChange(IVariable *pVar)
{
	InvalidateTM(	TM_POS_CHANGED | TM_ROT_CHANGED | TM_SCL_CHANGED);
}

//////////////////////////////////////////////////////////////////////////
void CCloudObject::GetLocalBounds( AABB &box )
{
	Vec3 diag(m_width, m_length, m_height);
	box = AABB( -diag/2, diag/2);
}

//////////////////////////////////////////////////////////////////////////
int CCloudObject::MouseCreateCallback( CViewport *view,EMouseEvent event,CPoint &point,int flags )
{
	if (event == eMouseMove || event == eMouseLDown || event == eMouseLUp)
	{
		SetPos( view->MapViewToCP( point ) );

		if (event == eMouseLDown) {
			SW_TEST_OBJ_PLACETO_MCB(GetPos(), GetLayer(), true);
			SW_ON_OBJ_NEW(this);
			return MOUSECREATE_OK;
		}

		return MOUSECREATE_CONTINUE;
	}
	return CBaseObject::MouseCreateCallback( view,event,point,flags );
}

//////////////////////////////////////////////////////////////////////////
void CCloudObject::Display( DisplayContext &dc )
{
	const Matrix34 &wtm = GetWorldTM();
	Vec3 wp = wtm.GetTranslation();

	if (IsSelected())
		dc.SetSelectedColor();
	else if (IsFrozen())
		dc.SetFreezeColor();
	else
		dc.SetColor( GetColor() );

	dc.PushMatrix( wtm );
	AABB box;
	GetLocalBounds(box);
	dc.DrawWireBox( box.min,box.max);
	dc.PopMatrix();

	DrawDefault( dc );
}

//////////////////////////////////////////////////////////////////////////
bool CCloudObject::HitTest( HitContext &hc )
{
	Vec3 origin = GetWorldPos();

	AABB box;
	GetBoundBox(box);

	float radius = sqrt((box.max.x-box.min.x) * (box.max.x-box.min.x) + (box.max.y-box.min.y) * (box.max.y-box.min.y) + (box.max.z-box.min.z) * (box.max.z-box.min.z))/2;

	Vec3 w = origin - hc.raySrc;
	w = hc.rayDir.Cross( w );
	float d = w.GetLength();

	if (d < radius + hc.distanceTolerance)
	{
		hc.dist = hc.raySrc.GetDistance(origin);
		return true;
	}
	return false;
}